﻿using System;
using System.Collections;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using PoolGame2.Physics;
using PoolGame2.Game;

namespace PoolGame2.Controls
{
    public class PCGameControls : GameControls
    {
        private Dictionary<Keys, ControlActions> keyDownControlMappings = new Dictionary<Keys, ControlActions>();
        private Dictionary<Keys, ControlActions> keyPressedControlMappings = new Dictionary<Keys, ControlActions>();
        private MouseState originalMouseState;
        private bool leftButtonDown = false;

        public PCGameControls(PoolGame game) : base(game)
        {
            //keyPressedControlMappings.Add(Keys.PageUp, ControlActions.CAMERA_CYCLE_UP);
            //keyPressedControlMappings.Add(Keys.PageDown, ControlActions.CAMERA_CYCLE_DOWN);
            keyPressedControlMappings.Add(Keys.T, ControlActions.SWITCH_TRACKING);

            keyDownControlMappings.Add(Keys.W, ControlActions.MOVE_FORWARD);
            keyDownControlMappings.Add(Keys.S, ControlActions.MOVE_BACK);
            keyDownControlMappings.Add(Keys.A, ControlActions.STRAFE_LEFT);
            keyDownControlMappings.Add(Keys.D, ControlActions.STRAFE_RIGHT);

            keyDownControlMappings.Add(Keys.Up, ControlActions.DPAD_UP);
            keyDownControlMappings.Add(Keys.Down, ControlActions.DPAD_DOWN);
            keyDownControlMappings.Add(Keys.Left, ControlActions.DPAD_LEFT);
            keyDownControlMappings.Add(Keys.Right, ControlActions.DPAD_RIGHT);

            keyDownControlMappings.Add(Keys.Y, ControlActions.REPLAY_YES);
            keyDownControlMappings.Add(Keys.N, ControlActions.REPLAY_NO);

            AddDebugMappings();

            Mouse.SetPosition(GameConstants.SCREEN_WIDTH / 2, GameConstants.SCREEN_HEIGHT/ 2);
            originalMouseState = Mouse.GetState();
        }

        private void AddDebugMappings()
        {
            keyPressedControlMappings.Add(Keys.F1, ControlActions.DEBUG_SWITCH);
            keyPressedControlMappings.Add(Keys.F2, ControlActions.DEBUG_CUSHION_EDIT_MODE);
            keyPressedControlMappings.Add(Keys.F3, ControlActions.DEBUG_FAST_MOVE);
            keyDownControlMappings.Add(Keys.D0, ControlActions.DEBUG_0);
            keyDownControlMappings.Add(Keys.D1, ControlActions.DEBUG_1);
            keyDownControlMappings.Add(Keys.D2, ControlActions.DEBUG_2);
            keyDownControlMappings.Add(Keys.D3, ControlActions.DEBUG_3);
            keyDownControlMappings.Add(Keys.D4, ControlActions.DEBUG_4);
            keyDownControlMappings.Add(Keys.D5, ControlActions.DEBUG_5);
            keyDownControlMappings.Add(Keys.D6, ControlActions.DEBUG_6);
            keyDownControlMappings.Add(Keys.D7, ControlActions.DEBUG_7);
            keyDownControlMappings.Add(Keys.D8, ControlActions.DEBUG_8);
            keyDownControlMappings.Add(Keys.D9, ControlActions.DEBUG_9);
            keyDownControlMappings.Add(Keys.NumPad2, ControlActions.DEBUG_D);
            keyDownControlMappings.Add(Keys.NumPad4, ControlActions.DEBUG_L);
            keyDownControlMappings.Add(Keys.NumPad6, ControlActions.DEBUG_R);
            keyDownControlMappings.Add(Keys.NumPad8, ControlActions.DEBUG_U);
        }

        public override void PollController(GameTime gameTime)
        {
            List<GameControlAction> actions = new List<GameControlAction>();

            HandleKeys(actions);
            if( !this.InMenu && ((PoolGame)Game).IsActive)
                HandleMouse(actions);

            if (actions.Count > 0)
            {
                this.NotifyListeners(actions);
            }
        }

        private void HandleKeys(List<GameControlAction> actions)
        {
            foreach (System.Collections.Generic.KeyValuePair<Keys, ControlActions> pair in keyPressedControlMappings)
            {
                if (IsKeyPressed(pair.Key))
                {
                    GameControlAction action = new GameControlAction(pair.Value);
                    actions.Add(action);
                }
            }
            foreach (System.Collections.Generic.KeyValuePair<Keys, ControlActions> pair in keyDownControlMappings)
            {
                if (IsKeyDown(pair.Key))
                {
                    GameControlAction action = new GameControlAction(pair.Value);
                    actions.Add(action);
                }
            }

        }

        private void HandleMouse(List<GameControlAction> actions)
        {
            MouseState currentMouseState = Mouse.GetState();
            if (currentMouseState != originalMouseState)
            {
                int scrollwheel = currentMouseState.ScrollWheelValue - originalMouseState.ScrollWheelValue;
                if (scrollwheel < 0)
                {
                    actions.Add(new GameControlAction(ControlActions.CAMERA_CYCLE_DOWN));
                }
                if (scrollwheel > 0) {
                    actions.Add(new GameControlAction(ControlActions.CAMERA_CYCLE_UP));
                }
                if (currentMouseState.LeftButton == ButtonState.Pressed)
                {
                    actions.Add(new GameControlAction(ControlActions.START_SHOT));
                    leftButtonDown = true;
                }
                if (currentMouseState.LeftButton == ButtonState.Released && leftButtonDown)
                {
                    actions.Add(new GameControlAction(ControlActions.END_SHOT));
                    leftButtonDown = false;
                }
                
                if (currentMouseState.RightButton == ButtonState.Pressed)
                {
                    actions.Add(new GameControlAction(ControlActions.MOUSE_RIGHT_CLICK));
                }
                
                float xDifference = (currentMouseState.X - originalMouseState.X);
                float yDifference = (currentMouseState.Y - originalMouseState.Y);
                if (xDifference != 0 || yDifference != 0)
                {
                    GameControlAction action;
                    if (IsKeyDown(Keys.LeftAlt))
                    {
                        action = new GameControlAction(ControlActions.CUE_TIP_MOVEMENT);
                    }
                    else if (IsKeyDown(Keys.LeftControl))
                    {
                        action = new GameControlAction(ControlActions.CUE_MOVEMENT);
                    }
                    else
                    {
                        action = new GameControlAction(ControlActions.ANALOG2_MOVE);
                    }
                    action.AddProperty(GameConstants.X_CHANGE, xDifference);
                    action.AddProperty(GameConstants.Y_CHANGE, yDifference);
                    actions.Add(action);
                }

            }
            Mouse.SetPosition(GameConstants.SCREEN_WIDTH / 2, GameConstants.SCREEN_HEIGHT / 2);
            originalMouseState = Mouse.GetState();
        }

    }
}
